/**
 * 给定N个点，每个点有目标权值Ai，初始权值为零
 * 给定M条候选边。做如下操作：
 * 1. 可以选择一条没有用过的侯选边，进行连边
 * 2. 选择一个连通子图将所有点的当前权值加1
 * 目标是使得每个点的权值恰好等于Ai，问所需的操作2的最少次数
 * 操作1可以最多进行min(5N, M)次。
 * 注意到如果候选边允许的话，将整个图连通的操作1数量为N-1，所以操作1的限制可以无需考虑
 * 专心考虑操作2即可
 * 
 * 由于累加有Ai的限制，因此我们应该先将权值大的节点加到一定程度，再把权值小的节点加入连通块累加
 * 再加到一定程度，再把更小的点加入连通块
 * 
 * 这样考虑比较麻烦，倒过来考虑。令初始权值为Ai，进行减法，减到零即可。答案是一样的。
 * 如此操作，则连通块上所有的点的权值均相等，称作连通块的权值，一起往下减。
 * 对当前连通块，在所有邻点中选择权值小于当前连通块的最大值，将其合并，且差值加入答案。
 * 但这个顺序比较麻烦，采用一种反向操作。
 * 
 * 初始令ans=SIGMA{Ai}，如果图不连通的话，这就是答案。
 * 然后根据连通的情况，可以确定某些Ai是不用放到答案中的，
 * 因为这些Ai会随着连通块一起减掉，连通块中只要有一个代表对答案有贡献即可。
 *  
 * 将Ai从大到小排序，对每一个i
 *     对i的每一个邻点v:
 *         如果i、v已经连通，则continue
 *         如果i连通块的权值大于v连通块的, continue
 *         到此说明i连通块对答案没有贡献, ans -= rank[i]
 *         unite(i, v)         
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using pii = pair<int, int>;

struct uf_t{
vi father, rank;
void init(int n){
    father.assign(n + 1, 0);for(int i=1;i<=n;++i)father[i]=i;
    rank.assign(n + 1, 0);
}
int find(int x){
    return x == father[x] ? x : father[x] = find(father[x]);
}
void unite(int x, int y){
    y = find(y);
    x = find(x);
    if(rank[y] < rank[x]) father[x] = y;
    else father[y] = x;
}

}UF, U;

int N;
int M;
vi A;
vector<vi> G;


llt proc(){
    vector<pii> vec; vec.reserve(N);
    for(int i=1;i<=N;++i) vec.emplace_back(i, A[i]);
    sort(vec.begin(), vec.end(), [](const pii & a, const pii & b){
        if(a.second != b.second) return a.second > b.second;
        return a.first < b.first;
    });

    llt ans = accumulate(A.begin(), A.end(), 0LL);

    for(const auto & p : vec){
        for(auto v : G[p.first]){
            int fu = UF.find(p.first);
            int fv = UF.find(v);
            if(fu == fv or UF.rank[fu] > UF.rank[fv]) continue;

            ans -= UF.rank[fu];
            UF.unite(p.first, v);
        }
    }

    return ans;
}

void work(){
    cin >> N >> M;
    A.assign(N + 1, {});
    for(int i=1;i<=N;++i) cin >> A[i];

    UF.init(N);
    for(int i=1;i<=N;++i) UF.rank[i] = A[i];

    G.assign(N + 1, {});
    for(int a,b,i=0;i<M;++i){
        cin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }

    cout << proc() << endl;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--){	
        work();
	}
    return 0;
}